use std::{collections::HashMap, ops::Deref};

// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
    pub val: i32,
    pub next: Option<Box<ListNode>>,
}

impl ListNode {
    #[inline]
    #[allow(dead_code)]
    fn new(val: i32) -> Self {
        ListNode { next: None, val }
    }
}

struct Solution {}

impl Solution {
    #[allow(dead_code, unused_variables)]
    pub fn merge_two_lists(
        list1: Option<Box<ListNode>>,
        list2: Option<Box<ListNode>>,
    ) -> Option<Box<ListNode>> {
        None
    }

    pub fn merge_two_lists2(
        list1: Option<Box<ListNode>>,
        list2: Option<Box<ListNode>>,
    ) -> Option<Box<ListNode>> {
        match (list1, list2) {
            (Some(v1), Some(v2)) => {
                if v1.val < v2.val {
                    Some(Box::new(ListNode {
                        val: v1.val,
                        next: Solution::merge_two_lists2(v1.next, Some(v2)),
                    }))
                } else {
                    Some(Box::new(ListNode {
                        val: v2.val,
                        next: Solution::merge_two_lists2(Some(v1), v2.next),
                    }))
                }
            }
            (Some(v1), None) => Some(v1),
            (None, Some(v2)) => Some(v2),
            (None, None) => None,
        }
    }

    pub fn merge_k_lists(mut lists: Vec<Option<Box<ListNode>>>) -> Option<Box<ListNode>> {
        let mut min_value = i32::MAX;
        let mut min_index = i32::MIN;
        for (index, first_node) in lists.iter().enumerate() {
            if let Some(node) = first_node {
                if node.val < min_value {
                    min_value = node.val;
                    min_index = index as i32;
                }
            }
        }

        if min_index == i32::MIN {
            None
        } else {
            lists[min_index as usize] = lists[min_index as usize].take().unwrap().next;

            Some(Box::new(ListNode {
                val: min_value,
                next: Solution::merge_k_lists(lists),
            }))
        }
    }

    pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
        let mut hash_table = HashMap::new();
        let mut index = 0;
        nums.iter()
            .find(|i| {
                if hash_table.contains_key(&(target - *i)) {
                    true
                } else {
                    hash_table.insert(**i, index);
                    index += 1;
                    false
                }
            })
            .map_or(vec![], |i| {
                vec![index, *hash_table.get(&(target - *i)).unwrap()]
            })
    }

    pub fn is_palindrome(x: i32) -> bool {
        if x < 0 {
            false
        } else {
            let mut val = x;
            let mut val_reverse = 0;
            while val != 0 {
                val_reverse = val_reverse * 10 + (val % 10);
                val = val / 10;
            }
            println!("{} - {}", x, val_reverse);
            val_reverse == x
        }
    }
}

#[derive(Clone)]
struct A {}

impl Deref for A {
    type Target = A;
    fn deref(&self) -> &A {
        println!("A deref");
        return self;
    }
}

impl Drop for A {
    fn drop(&mut self) {
        println!("A drop");
    }
}

fn main() {
    println!("hello!");
    let v = vec![15, 7, 11, 2];
    let r = Solution::two_sum(v, 9);
    println!("{:?}", r);

    let x = 121;
    println!("{}", Solution::is_palindrome(x));

    let list1 = Some(Box::new(ListNode { val: 7, next: None }));
    let list2 = Some(Box::new(ListNode {
        val: 1,
        next: Some(Box::new(ListNode { val: 3, next: None })),
    }));
    println!(
        "{:?}",
        Solution::merge_two_lists2(list1.clone(), list2.clone())
    );
    let _a = Some(Box::new(A {}));
    let mut _a2 = _a.clone();
    let _p = Box::into_raw(_a.unwrap());
    let _aa: Box<A> = unsafe { Box::from_raw(_p) };

    let lists = vec![list1, list2.clone(), list2];
    println!("merge_k_lists={:?}", Solution::merge_k_lists(lists));
}
